﻿using System;
using System.Threading;

namespace SharpTrainer.Event
{
    internal class MailManager
    {
        public static void Go()
        {
            // Construct a MailManager object
            MailManager mm = new MailManager();

            // Construct a Fax object passing it the MailManager object
            Fax fax = new Fax(mm);

            // Construct a Pager object passing it the MailManager object
            Pager pager = new Pager(mm);

            // Simulate an incoming mail message
            mm.SimulateNewMail("Peter", "Simon", "Hi, how are you?");

            // Force the Fax object to unregister itself with the MailManager
            fax.Unregister(mm);

            // Simulate an incoming mail message
            mm.SimulateNewMail("Mary", "Peter", "Hello there!");
        }

    #if CompilerImplementedEventMethods
        //Define the event member 
	    public event EventHandler<NewMailEventArgs> NewMail;
    #else
        // Add private field which refers to the head of the delegate linked-list
        private EventHandler<NewMailEventArgs> m_NewMail;

        // Add an event member to the class
        public event EventHandler<NewMailEventArgs> NewMail
        {
            // Explicitly implement the 'add' method
            add
            {
                // Without thread-safety, add a handler 
                // (passed as 'value') to the delegate linked list
                m_NewMail += value;
            }

            // Explicitly implement the 'remove' method
            remove
            {
                // Without thread-safety, remove a handler 
                // (passed as 'value') from the delegate linked list
                m_NewMail -= value;
            }
        }

    #endif

        //Define a method responsible for raising the event 
        // to notify registered objects that the event has occurred
        // If this class is sealed, make this method private and nonvirtual
        protected virtual void OnNewMail(NewMailEventArgs e)
        {
            // Copy a reference to the delegate field now into a temporary field for thread safety 
            //e.Raise(this, ref m_NewMail);

    #if CompilerImplementedEventMethods
		EventHandler<NewMailEventArgs> temp = 
            Interlocked.CompareExchange(ref NewMail, null, null);
    #else
            EventHandler<NewMailEventArgs> temp =
             Interlocked.CompareExchange(ref m_NewMail, null, null);
    #endif

            // If any methods registered interest with our event, notify them 
            if (temp != null) temp(this, e);
        }

        //Define a method that translates the 
        // input into the desired event
        public void SimulateNewMail(String from, String to, String subject)
        {

            // Construct an object to hold the information we wish
            // to pass to the receivers of our notification
            NewMailEventArgs e = new NewMailEventArgs(from, to, subject);

            // Call our virtual method notifying our object that the event
            // occurred. If no type overrides this method, our object will
            // notify all the objects that registered interest in the event
            OnNewMail(e);
        }
    }
}
